﻿using Surf.GrpcInvoker.Demo.Core.CallHandlers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace Surf.GrpcInvoker.Demo.Core
{
    public class Server
    {
        private readonly List<ServerServiceDefinition> _serviceDefinitionsList = new List<ServerServiceDefinition>();
        private readonly Dictionary<string, IServerCallHandler> _callHandlers = new Dictionary<string, IServerCallHandler>();
        private readonly object server_Lock = new object();

        public Server()
        {
            Services = new ServiceDefinitionCollection(this);
            // Todo ThreadPool
            // Todo Channel & ServerHandle
        }

        internal void AddServiceDefinitionInternal(ServerServiceDefinition serviceDefinition)
        {
            lock (server_Lock)
            {
                foreach (var handler in serviceDefinition.CallHandlers)
                {
                    _callHandlers.Add(handler.Key, handler.Value);
                }
                _serviceDefinitionsList.Add(serviceDefinition);
            }
        }

        public ServiceDefinitionCollection Services { get; }

        public void Start()
        {
            // Todo 启动线程
        }

        // 模拟调用
        internal Task ImitateCall(string methodName, byte[] message)
        {
            try
            {
                //IServerCallHandler callHandler;
                if (!_callHandlers.TryGetValue(methodName, out IServerCallHandler callHandler))
                {
                    callHandler = EmptyCallHandler.Instance;
                }
                return callHandler.HandleCall(message);
            }
            catch (Exception ex)
            {
                // Todo Logger
                throw ex;
            }
        }

        public class ServiceDefinitionCollection : IEnumerable<ServerServiceDefinition>
        {
            private readonly Server _server;
            internal ServiceDefinitionCollection(Server server)
            {
                _server = server;
            }

            public void Add(ServerServiceDefinition definition)
            {
                _server.AddServiceDefinitionInternal(definition);
            }

            public IEnumerator<ServerServiceDefinition> GetEnumerator()
            {
                return _server._serviceDefinitionsList.GetEnumerator();
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return _server._serviceDefinitionsList.GetEnumerator();
            }
        }
    }
}
